Hey there.
In this lecture, we're going to continue using object oriented programming to create land mines.
We'll be using the concept of composition.
And we'll also be using the collection service to create the land mine you see here.
So let's go ahead and playtest our game.
And I'll demonstrate to you what our land mine does.
So we can go and walk over to our land mine.
And once we touch it boom.
We blow up the land.
Mine disappears and we've taken some damage.
Now, before we begin, you'll have to grab this landmine model that I've attached to the lecture.
And this model simply contains a module script.
And inside this module script we have some basic properties, such as the properties we'll have for
our explosion, as well as how much damage the explosion does per hit and the weight sensitivity for
our landmine.
You're also going to need a plugin.
And this plugin is called tag editor or instance tagging.
And I've also attached this plugin to the lecture.
So you can go ahead and grab that.
So you can modify the tags of parts and instances in your game.
So once you have this plugin downloaded and installed in studio, you can go ahead and open it up here.
And what this plugin will allow you to do is to create a new tag that you can attach to instances in
your game.
In this case, we're going to create a new tag.
I'm going to call it landmine.
And using this tag we can now attach it to objects in our game.
So for example if I select this landmine and then I select my part, you'll see this checkbox appear.
And when I select this checkbox that means this instance now has this landmine tag attached to it.
So if I go and look under tagged instances here, my landmine shows up in this list.
And because that our land mine is now tagged, we can use the collection service to gather every single
instance in our game that has this land mine tag.
And it doesn't matter where our instance is stored, it could be in a folder and a model.
It could be in a different service.
But because it has this land mine tag attached to it, we can go ahead and collect all of them.
And that's the very useful thing about the collection service.
So once you have this tag added to your land mine, we can go ahead and start getting scripting.
Inside of this module script I've created.
I've just called it landmine, and this module script is going to act as my class.
And in here we're going to need a few things.
Of course we're going to need some services.
Nothing too crazy.
The first thing we'll need is the server storage service.
And the reason I'm getting this is because my classes are stored in this service.
So we're going to head and get that.
And we're also going to get the collection service.
Election service, and we're going to be using that in a moment.
Now we're also going to need some variables to set up our class again to uphold encapsulation, I'm
going to create two different tables.
One I'll just call landmine.
And this will act as a table to store my constructor.
And then I'm going to create another one I'll call it MT short for meta table.
And it's going to store all the functions for the objects of this class.
And these objects are going to have quite a few properties.
One is going to be the part or the landmine that is representing this object.
We'll have a property for whether or not it's enabled, and we'll set it to true by default.
We'll have a condition to check whether or not it has been detonated, detonated set it to false.
We're going to create a property for the properties module script in our landmine, call it properties
and just set it to null for now.
And we'll have a property for the explosive.
And you'll see what I mean in a minute because we're going to create another class.
And this class is going to represent an explosion.
And we're going to take an object from that class and store it within our landmine object.
So we're upholding this idea of composition.
After that, we can set the landmine meta tables underscore underscore index meta method to itself.
That way we can access all these properties and functions.
The next thing I'm going to do is I'm going to create a variable for this explosion class.
I'll just call it explosion.
And I'm going to require from my server storage in a folder called classes, where I have the explosion
module script.
And we're going to be filling this out in a little bit.
Not currently, but we're going to continue setting up our landmine class.
I'm going to have a table that's going to store all the current landmine objects.
And I'm going to create a boolean here.
I'll call it initialized set to false.
But what I'm going to do is I'm going to create a function called init which is short for initialize.
And it's going to go and set up everything for us.
So it's going to use the collection service and collect all the landmines in our game and create objects
for them.
And then it'll set initialize to true.
So we don't have to initialize this class anymore.
And then I'm going to add one constant.
And this constant is going to be for that tag we made I'll call it landmine tag.
And it's just going to be a string that is landmine.
So the exact same string as the one we created for our tag.
Next, we're going to need a section for some private functions, because we need to abstract our class
and hide any unimportant details we don't need to see on the outside.
So one function I will call get total weight.
And I'll pass a part to it.
So what this function is going to do is that when our landmine gets touched, it's going to check the
weight of that part.
And if that part is a part of a model, then it'll check the entire weight of the model.
That way if the weight reaches a specific threshold, then the bomb will blow up.
But if it's something that's too light, then the bomb won't blow up at all.
And then we're also going to have a function where when our landmine gets touched, we're going to call
it on landmine touched, and we're going to have to pass the object as well as the other part that touched
the landmine.
We'll fill this out in a little bit.
And the next.
We need a section for some public functions like our constructor and things like that.
So the first thing I'll create actually is the initialize function.
I'm going to just call it init short for initialize.
And we're going to check that boolean.
So if we've already initialized this class then we're just going to return.
Otherwise we're going to set initialize to true.
And then what we can do is we can get all of the landmines in our game by using the collection service.
And there's a function in the collection service called Get Tagged right here.
And it returns to us an array of objects in the game with a given tag.
So we can pass that string.
We just made the landmine tag, and now every single instance in our game is going to be stored in a
table that has the tag of landmine.
Then we can go and we can loop through every single landmine that's in this table.
And we can use a constructor function to create new landmine objects.
So we'll actually make that right now.
So function landmine dot new.
So this is our constructor.
We have to pass a part to this function.
And I'll designate it as a part.
And this part has to be our landmine.
So we're going to create a table we'll call it self and attach the landmine meta table to this new table.
And then from that point we have access to all those properties we made earlier.
So we can set the part equal to the part pass to the function.
We can set the properties equal to the parts property.
So remember we have a module script in our landmine that we're going to require.
So we can require part.
And then the dot properties.
So we get the properties for our landmine.
And now we can set the self dot explosive equal to.
We'll reference our explosion class.
And in there we're also going to be creating a dot new function or a constructor.
We haven't made one yet.
So we're just going to leave this blank for now.
But we'll fill it out in a little bit.
And then I think an extra property will actually add to this table is a connection, and it's going
to be connected to our part.
And when it gets touched we're going to connect a function to it.
And from there we can call that on landmine touch function and pass the object itself, as well as the
other part that touched our part which is passed to this lambda function.
Again, we're going to fill out this function in a little bit.
And then once we do all that, then we can insert our object into that table.
We created current landmines and insert self.
And then finally we can return self back to where this function was called.
Some other functions we're going to need will be now a part of our landmine meta table.
So landmine empty.
We're going to have a function to explode the landmine.
We're also going to have a function to enable or disable our landmine so we can make it, uh, you know,
hostile or docile.
So we'll have one to enable it and we'll have one to disable it.
Now let's say we also wanted to repair our landmine.
So let's say it got detonated.
And a little while later we wanted the landmine to respawn so we could create a function like landmine
empty.
We'll call it like repair.
And in here we can repair the landmine back to its previous state so it can be ready for another detonation.
So this seems pretty good so far.
I think what we'll do is start filling out some of these functions.
So what do we want to do to enable our landmine?
Well we can just do self dot enabled equal to true.
And in here we can just do self dot enabled equal to false.
Pretty simple.
So now that we've created our constructor, we can pass the new function here because it belongs to
this table.
Even though we created this function after this function was created, because it belongs to this table,
and we're going to be calling this function later, we're able to access our constructor here.
And then we can pass that landmined.
To the function.
So now if we call this function outside in a server script, all we need to do is call init.
And every single landmine in our game will be set up and ready to go.
Now another thing we can do is fill out the explode function.
So what do we want to happen when this function gets called?
Well we want to blow up the landmine right.
But we first have to check a couple criteria such as these booleans we created up here.
So for example if a landmine is disabled then we don't want to blow it up.
So if not self dot enabled.
Then we're going to print something like landmine is disabled and we'll just return end.
And then we also need to check if this landmine has already been detonated.
So self dot detonated.
Then we'll print.
Landmine already exploded and then we're going to return end.
Otherwise we'll set self dot detonated to true because we're about to blow up the landmine.
And from this point, this is where we would take this explosion object.
We would create and call a function on it to blow up, you know, an explosion.
So we'll make a note for that here.
Blow up explosive.
And after that explosive gets blown up, we can disable this landmine.
Calling the disable function, we can set the part dot transparency transparency equal to one so the
landmine is invisible.
And then we could also do something like part dot can collide equal to false.
So we can't collide with an invisible landmine.
And then what we could do down here is that we could repair the landmine simply by re-enabling it.
So we could do um.
Self dot detonated equal to false.
And then we can set the party transparency back to be opaque, and then we'll make sure to turn on can
collide again.
And then we can enable the landmine.
I think that's all we need to do there.
Now, back up here, I think it is time for us to.
Ah, yes.
Let's fill out these functions right here.
So what do we want to happen when our land mine gets touched?
Well, first off, we should check if the land mine has already been detonated.
Because if it has, we don't want to detonate it again.
So if self dot detonated, then we're going to return.
Um, another thing we need to make sure of is that whatever part's touching, our landmine isn't anchored.
We only want to look at unanchored parts, because when the game starts, the landmine is going to be
touching the ground, and the ground's anchored and the ground has a lot of mass, so it's going to
blow up the landmine.
But we don't want that to happen.
So we need to do, um, if this other part that touched this landmine is anchored, then we're going
to ignore it, all right?
We don't care about it.
Otherwise we can get the weight of this part and any other parts that it may be part of in a model.
By using this get total weight function, we're about to fill out, and we can return a number from
this function.
We can store it in a variable called weight, get total weight, and pass this other part.
And let's go ahead and fill out this function.
So what we could do is create a variable called total weight.
Set it to nothing for now.
And then we can check if this part um, or actually if the part parent is a model.
So this part is part of a model.
Then we can set total weights equal to zero.
And we're going to loop through every single child and ipairs part dot parent.
And we're going to get all of the descendants.
So everything that is a part of this model.
And what we'll do is we're going to make sure that this child is a base part.
So if not, child is a.
Bass part.
Then we're going to continue looping.
Otherwise we can set total weight plus equal to the child dot I believe it's mass.
So all bass parts have a property called mass and we'll add it to the total weight.
And then once this is done looping, what we're going to do is we're going to return the total weight.
But let's say this part was by itself and it wasn't a parent or it wasn't a child of a model.
We just want to pass the weight of the part instead.
Instead of this total weight that never got instantiated here.
So we could put an Or statement here and do part dot mass.
So just in case total weight hasn't been instantiated yet because the part is not part of a model,
then we'll just pass the parts mass just by itself.
So now we get our number from this function stored in this variable here.
And then we can check if the weight is greater than or equal to the self dot properties of this object,
and the property is called weight sensitivity.
So if it's greater than or equal to the weight sensitivity.
Then we can blow up the landmine.
Seems good.
So we blow up the landmine.
Landmine gets detonated only when it gets touched once.
Um, we've initialized everything.
I think the next thing we need to do is to fill out, um, for our explosion class, we got to make
this constructor function.
So let's go ahead and do that.
Let's go into our explosion class and let's get working.
So inside of our explosion class I don't think we'll need any services.
We'll just need some variables.
Again we're going to uphold encapsulation.
We'll create two tables one for storing the constructor.
And another to be the meta table for this class.
So explosion empty.
We'll call it, um, an explosion in Roblox needs to have a position.
And the position will be, um, the landmine.
Right?
The position of the landmine.
So we could pass the landmine to the constructor for this explosion, and we could store it in a property.
We could just call it parent.
We can set the explosions parent to this landmine.
We'll set it to nil for now.
And I think we'll also need to access the properties that are inside of our landmine part.
So we'll set it to nil for now as well.
And again make sure to set the underscore underscore index meta method to itself.
And then from here we're going to need a few constants.
So let's say just in case somebody forgot to fill out some of the properties here and the explosion
properties or they didn't fill it out correctly.
Well we either want to supply the properties for our explosion instance to be either these or we could
set it to a default.
So let's define some defaults.
And we'll just set it to the world origin as default.
So that's a new vector three at world origin.
So good.
Now we can create some private functions for this class to, you know, hide away unnecessary details.
We'll have a function for creating the explosion, this explosion instance.
And actually we'll need another function above it.
I'm going to call it on explosion hit, because an explosion instance has a hit event, and it goes
through and tells us all the parts that the explosion hit.
And from that we can see if the part we hit belonged to a humanoid, and we can damage the humanoid
accordingly to that.
So we'll make sure to call this function on that event.
Otherwise we'll just need some public functions like the constructor.
So we'll do function explosion dot new.
What do we need to pass to this constructor?
Well of course we need the parent or the landmine.
Right.
The part that has the properties module script in it.
Um, we should probably pass to this function.
The amount of damage we want to do.
And that'll be part of a number.
We'll pass again.
The blast pressure.
The blast radius.
All right, so now that we've got that done, um, we'll create a new table called Self Equal.
To set the table, create a new table, attach explosion meta table to it.
Uh, the self dot parent is going to be equal to the parent.
And actually.
Um.
Never mind.
We don't need to define it there.
But we do need to have a damage property we can set.
We'll set it to zero.
That way, we know that we need a damage property right here.
The damage is equal to the damage passed to this function.
And actually, I think a better way that we could do this instead of having so many arguments we need
to pass to the function.
We could just set it up in here where all of these properties are actually a dictionary.
So let's actually do that.
Um, I'll create a new explosion instance here so you can see the names of the properties.
Here's all the property names.
Again this is blast pressure.
Make sure you match all the capitalization.
But I'm pretty sure I'll update this instance or the model attached to the lecture to include this new
stuff.
So blast pressure equal to 600,000.
The blast radius equal to this.
We will have the destroy joint radius percent.
We're going to have.
The explosion type.
Well, let's actually make this table a little bigger.
And then the last one here is going to be the time scale.
And I don't think we need to store the position in here.
We'll take care of that inside of our module script here.
So instead what we could do is we could just have the player pass the properties table to us, and then
we can just store that here.
Instead.
I think that's a lot simpler.
Um.
Oh, yeah.
We also need to pass the damage.
So we'll store the damage.
We'll have the part that's going to be the parent of our explosion, the properties for the explosion.
All right.
All is good.
So we set all of that up.
And then I think that's actually it.
We can just return self here.
That's all we need to do for our explosion setup.
And that unfortunately, means I have to get rid of all of my hard work for Constance.
How sad.
It's okay.
I'll leave a note in the video so you don't have to fill that out by yourself.
Anyways, another function we'll have for this class is we're going to have a function called explode.
So when we want the our explosion object to blow up, we're going to blow it up.
And that's what we're using the create explosion function for.
And we'll pass self to it.
And then we'll have a section for main.
Which is just.
Returning back the explosion table because this is a module script.
And actually, let's make sure to do the same thing here because we haven't done that yet.
Have a main section to return back the landmine table.
So now we have our constructor created.
Um, I guess we go ahead and pass these arguments to it.
So here's our constructor right here.
We need to pass the part which is going to be the part passed to this function.
We need the damage which will be self dot properties dot damage.
And I believe it is yeah damage per hit damage per hit.
And then we need the properties for the explosion which will be stored in the module script.
So its explosion properties self dot properties dot explosion properties.
There we go.
And we're going to get an explosive object back from this constructor.
Now what do we want to do when this create explosion function is called?
Well, what we need to do is to create an explosion instance.
So explosion is equal to instance dot new explosion.
And then from this point, we can loop through every single property and every single value that is
in that properties table that's stored here.
So every single key and every single value.
So every single key, every value.
We're going to loop through all of them.
Set the property equal to this value in our explosion.
And we can do that by looping through it.
We'll make sure to pass Oh Self to this function.
So.
We do self dot properties.
And then we can set explosion this property.
Equal to the value.
Perfect.
So now our explosion has all the properties.
We also need to set up, um one more property.
We need to set the position.
So explosion dot position is going to be equal to self dot parents C frame.
That position.
And then we need to listen to an event in our explosion called Hit Like That.
And we're going to connect a Lambda function to it, get the part that this explosion hit.
And we're going to call the on explosion hit function.
That way we're able to pass self to it.
So past self and the part that got hit in the explosion.
And now to actually detonate the explosion, all we need to do is parent it to the workspace.
So we could do explosion dot parent equal to the self dot parent property which is our landmine part.
So it's going to go boom is what's going to happen.
And then we could wait some arbitrary amount of time, like five seconds.
So the explosion will be in the workspace for at least five seconds.
And then we can do explosion.
Destroy.
So we'll destroy the explosion after.
We don't need it that way.
You know, we don't have a bunch of explosions piling up in the workspace.
So now let's fill out the on explosion hit function.
Um, what we could do is fill out the parameter section.
Remember, we get the object and we get the part that was hit.
And then what we could do is we could check if there is a humanoid that was a part of this part that
got hit.
So part dot parent find first child, which is a humanoid.
If there is no humanoid, then we don't care.
We'll just return end.
Otherwise we can do humanoid.
Take damage equal to self.
Dot damage.
Just like that.
And I think that looks pretty good.
So we've got this filled out.
We pass the arguments we've needed to our constructor and then ah yes.
One more thing we have to do is that when we get this explode function called from when our landmine
gets touched, what we need to do is self dot explosive and call the explode function on it that exists
here within our explosion class.
So now what we need to do is run these module scripts by calling this initialize function.
So this is where my server script comes into play.
I'll just have one section for the services, which is to get the server storage.
Because again, this is where my classes are stored.
We're just going to need one variable.
That's our landmine class.
So we're going to require server storage dot classes folder and get my landmine class.
And then finally we'll have a section called main.
It's important to stay organized and we could do landmine init initialize.
So let's start up everything that means.
I think that means we're done.
So the only way to know if we're done is to test it.
Right?
So let's go ahead and test it out.
All right.
No errors in the console.
That's good.
That's always a thumbs up.
Now let's go and touch our landmine.
And there we go.
It blew up.
Um, unfortunately, our landmine is not disappearing instantly, and I think I know why.
So if we go to explosion.
Right.
So when we call the explode function, it calls this function.
And because it's yielding, um, we aren't able to get to this section until it's done yielding.
So what we could do is we could do task dot spawn spawn a lambda function here.
And that way we're exploding in a separate thread, and these can get run at the exact same time as
our, um, explosive object is exploding.
So let's go ahead and try that again.
So if we go and touch our landmine, boom!
And it's disappeared.
Perfect.
And now that means we should be able to duplicate this as many times as we want.
We can put these in whatever folders or parents we want, and each one of these things should be able
to blow up.
So if we go and touch one, boom blows up, we touch another, one, boom blows up and we're dead.
All right.
So congratulations on making it to the end of this lecture.
I know it was an earful and a lot of information to absorb, but I hope you're learning a lot so far,
and I hope this lecture has given you an example of how you can implement composition and the many other
object oriented principles in your game.
I'll see you in the next lecture.